<?php 
namespace auth;
use think\Db;
class Auth{
	/**
	 * @param  name 	需要验证的规则列表,支持逗号分隔的权限规则或索引数组
	 * @param  admin_id 认证用户的id
	 * @param  mode 	执行check的模式
	 * @param  relation 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
	 * @return bool 	通过验证返回true;失败返回false
	 */
	public function check($name,$admin_id,$mode = 'url',$relation = 'or'){

		//获取用户需要验证的所有有效规则列表
		$authList = $this->getAuthList($admin_id);

		if( 'url' == $mode ){
			$module = request()->module();
			$controller = request()->controller();
			$action = request()->action();

			$authWhere[] = ['m','=',$module];
			$authWhere[] = ['c','=',$controller];
			$authWhere[] = ['a','=',$action];
			$authWhere[] = ['status','=',0];

			$authCount = db('auth')->where($authWhere)->count();
			if($authCount <=0){
				return true;	
			}
			$name = [$module,$module."/".$controller,$module."/".$controller."/".$action];
			return $this->url_check($name,$authList,'url', $relation);
		}else{
			return $this->menu_check($name, $authList, $relation);
		}
	}

	/**
	 * @param  string|array $name 	需要验证的规则列表,支持逗号分隔的权限规则或索引数组
	 * @param  array 		$authList 用户需要验证的所有有效规则列表		
	 * @param  string 		$mdoe 执行check的模式
	 * @param  [type] 		$relation 如果为 'or' 表示满足任一条规则即通过验证;如果为 'and'则表示需满足所有规则才能通过验证
	 * @return [type]
	 */
	protected function url_check($name,$authList,$mode = 'url',$relation){
		//不为空
		if( !$authList || count($authList) <= 0 ){
			return true;
		}

		if( is_string($name) ){
			//转为小写
			$name = strtolower($name);
			//查找','在字符串中第一次出现的位置（数组字符串）
			if( strpos($name,',') !== false ){
				$name = explode(',', $name);
			}else{
				//单个
				$name = [$name];
			}
		}else{
			foreach ($name as $k => $v) {
				$name[$k] = strtolower($v);
			}
		}
		//保存验证通过的规则名
		$list = [];

		if( 'url' == $mode ){
			$REQUEST = unserialize(strtolower(serialize(request()->param())));
		}

		foreach ($authList as $auth) {
			$auth = strtolower($auth);
            $query = preg_replace('/^.+\?/U', '', $auth);

            if( 'url' == $mode && $query != $auth ){
            	parse_str($query, $param); //解析规则中的param
                $intersect = array_intersect_assoc($REQUEST, $param);
                $auth = preg_replace('/\?.*$/U', '', $auth);
                if (in_array($auth, $name) && $intersect == $param) {
                    //如果节点相符且url参数满足
                    $list[] = $auth;
                }
            }else{
            	if (in_array($auth, $name)) {
                    $list[] = $auth;
                }
            }
		}

		if ('or' == $relation && !empty($list)) {
            return true;
        }
        $diff = array_diff($name, $list);
        if ('and' == $relation && empty($diff)) {
            return true;
        }

        return false;
	}

	/**
	 * @param  int $admin_id 管理员id
	 * @return array $returnData 权限列表
	 */
	protected function getAuthList($admin_id){
		$adminInfo = db('administrator')->where('id = '. $admin_id)->find();
		$groupIdStr = $adminInfo['auth_group_id'];
		$groupIdList = explode(',', $groupIdStr);
		$groupIdList = array_unique($groupIdList);//删除重复
		$where[] = ['id',"in",$groupIdList];
		//得到权限id列表
		$authIdList = db('auth_group')->where($where)->select();
		$authIdList = array_unique($authIdList);
		$authIdList = $authIdList[0]['auth'];

		$where2[] = ['id','in',$authIdList];
		$authList = db('auth')->where($where2)->select();

		$returnData = [];
		foreach ($authList as $auth) {
			$authStr = '';
			$m = trim( $auth['m'] );
			$a = trim( $auth['a'] );
			$c = trim( $auth['c'] );
			$p = trim( $auth['p'] );

			if( !$m ) {
				continue;	
			}
			$authStr = $m;

			if( $c ){
				$authStr = $authStr."/".$c;
				$authStr = $a ? $authStr."/".$a : $authStr;
			}
			$authStr = $p ? $authStr."?".$p : $authStr;
			$returnData[] = $authStr;
		}
		return $returnData;
	}
}